<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

    <title>葡萄藤PPT</title>

    <link rel="stylesheet" href="../css/reveal/reveal.css">

    <!-- PPT主题，可以在/css/reveal/theme/中选择其他主题，目前暂时只能使用该模板 -->
    <link rel="stylesheet" href="../css/reveal/theme/ptt.css">

    <!-- syntax highlighting 代码高亮主题 -->
    <link rel="stylesheet" href="../lib/reveal/css/zenburn.css">

    <!-- 打印和PDF输出样式 -->
    <script>
        var link = document.createElement('link');
        link.rel = 'stylesheet';
        link.type = 'text/css';
        link.href = window.location.search.match(/print-pdf/gi) ? '../css/reveal/print/pdf.css' :
            '../css/reveal/print/paper.css';
        document.getElementsByTagName('head')[0].appendChild(link);
    </script>
</head>

<body>
    <img src="../img/demo/logo.png" alt="" usemap="#pttmap" class="base-logo">
    <map name="pttmap">
        <area shape="rect" coords="0,0,276,58" href="http://www.jnshu.com" alt="" target="_blank" />
    </map>
    <div class="reveal">
        <div class="slides">
            <section>
                <h2>【JS-04】js同步异步以及回调函数</h2>
                <p>上海分院小课堂第46期</p>
                <p>分享人：王梦男</p>
            </section>
            <section>
                <p>目录</p>
                <p>1.背景介绍</p>
                <p>2.知识剖析</p>
                <p>3.常见问题</p>
                <p>4.解决方案</p>
                <p>5.编码实战</p>
                <p>6.扩展思考</p>
                <p>7.更多讨论</p>
                <p>8.参考文献</p>
            </section>

            <section>
                <h3>1.背景介绍</h3>
            </section>

            <section>
                <p style="text-align: left">
                    <h3>什么是同步，什么是异步?</h3>
                </p>

            </section>
            <section>
                <p style="text-align: left">
                    同步指的是一次只能完成一件任务。如果有多个任务，就必须排队，前面一个任务完成，再执行后面一个任务，以此类推。
                </p>
                <p style="text-align: left">
                    异步指的是每一个任务有一个或多个回调函数（callback），前一个任务结束后，不是执行后一个任务，而是执行回调函数，后一个任务则是不等前一个任务结束就执行，所以程序的执行顺序与任务的排列顺序是不一致的、异步的。</p>

            </section>
            <section>
                <h3>2.知识剖析</h3>
            </section>
            <section>
                <section>
                    <h4>
                        javascript实现异步的原理？
                    </h4>
                    <p style="text-align: left">
                        首先js是单线程的语言，即同一时间只能做做一件事。那Js如何实现异步的，异步和单线程不是自相矛盾吗？其实，单线程和异步确实不能同时成为一个语言的特性。js选择了成为单线程的语言，所以它本身不可能是异步的，但js的宿主环境（比如浏览器，Node）是多线程的，宿主环境通过某种方式（事件驱动，下文会讲）使得js具备了异步的属性
                    </p>
                </section>
            </section>
            <section>
                <section>
                    <h4>
                        浏览器的内核是多线程的，它们在内核制控下相互配合以保持同步，一个浏览器至少实现三个常驻线程：javascript引擎线程，UI渲染线程，浏览器事件触发线程。
                    </h4>
                    <p style="text-align: left">
                        1.javascript引擎线程是基于事件驱动单线程执行的，JS引擎一直等待着任务队列中任务的到来，然后加以处理，浏览器无论什么时候都只有一个JS线程在运行JS程序。
                    </p>
                </section>
                <section>
                    <p style="text-align: left">
                        2.UI渲染线程负责渲染浏览器界面，当界面需要重绘（Repaint）或由于某种操作引发回流(reflow)时,该线程就会执行。但需要注意 UI渲染线程与JS引擎是互斥的，当JS引擎执行时UI线程会被挂起，UI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
                        <br/>
                        <br/> 3.事件触发线程，当一个事件被触发时该线程会把事件添加到待处理队列的队尾，等待JS引擎的处理。这些事件可来自JavaScript引擎当前执行的代码块如setTimeOut、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等，但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。
                    </p>
                </section>
                <section>
                    <img style="width: 100%; height: 100%" src="../img/js-4-Synchronization/liuchengtu.png" alt="">
                </section>
                <section>
                    <a href="../demo/js-04-Asynchronous-and-synchronous/demo2.html">UI线程和JS线程互斥的实例</a>
                    <p>
                        分析：第一个在keydown的时候，弹出来的是input里原来的value，而第2个在keydown的时候，却能弹出更新后的value，就是因为setTimeout，虽然他的delay设置为0，几乎是即时触发，但还是被添加到了执行队列后面，但就是这个过程，渲染已经完成了，当他回调函数执行时，输出来的已经是更新后的value了。</p>
                </section>
                <section>
                    <h4>注意：js的工作机制是当线程空闲的情况下才会执行异步代码的回调</h4>
                    <p style="text-align: left">即当所有同步任务执行完毕后才会执行异步任务的回调</p>
                    <a href="../demo/js-04-Asynchronous-and-synchronous/demo3.html">异步回调函数会在执行完所有同步任务后再执行</a>
                </section>
            </section>
            <section>
                <section>
                    总结：当Js执行到异步任务后，会将异步任务交给浏览器进行执行，当执行有结果时会把异步任务的回调函数插入待处理队列的队尾。
                </section>
            </section>
            <section>
                <h3>3.常见问题</h3>
            </section>
            <section>
                <section>
                    <h4>1.ajax发送异步请求浏览器做了什么</h4>
                </section>
                <section>
                    <h4>2.有哪些常见异步回调函数？</h4>
                </section>
            </section>
            <section>
                <h3>4.解决方案</h3>
            </section>
            <section>
                <h4>1.ajax发送异步请求浏览器做了什么？</h4>
                <p style="text-align: left">
                    1.Js创建了一个ajax请求
                    <br/> 2.浏览器另外开启一个ajax引擎线程，执行ajax请求
                    <br/> 3.执行得到响应后将回调函数放入任务队列中。
                    <br/> 4.Js执行任务队列中的回调函数。
                </p>
            </section>
            <section>
                <h4>2.有哪些常见的异步回调函数？</h4>
                <p>1.点击事件
                    <br/> 2.Ajax请求
                    <br/> 3.定时器
                </p>
            </section>
            <section>
                <h4>浏览器处理点击事件的过程</h4>
                <p>
                    <p>浏览器开启事件触发线程，等待用户动作，事件触发线程解析为响应事件，转移到javascript引擎线程，排队等候，等待javascript引擎的处理。</p>
                </p>
                <a href="../demo/js-04-Asynchronous-and-synchronous/demo4.html">点击触发事件等到同步任务执行完再执行</a>
            </section>
            <section>
                <h3>5.编码实战</h3>
            </section>
            <section>
                <h3>6.扩展思考</h3>
            </section>
            <section>
                <h4>异步函数有哪些优点和缺点？</h4>
                <p>优点：</p>
                <p> a）对CPU的使用率高。
                <br>
                b）不用考虑线程间同步互斥问题。
                <br>
                缺点：
                <br>
                a）实现较复杂，要把所有会导致阻塞的操作转化为异步操作。
                <br>
                b）并发性不好，在有的事件需要长时间占用CPU处理的情况下，其他事件会长时间等待得不到处理。
                <br>
                c）在多CPU时不如多线程高效。</p>
            </section>
            <section>
                <h3>7.更多讨论</h3>
            </section>
            <section>
                <h3>8.参考文献</h3>
            </section>
            <section>
                <p>参考一：
                    <a href="https://www.cnblogs.com/woodyblog/p/6061671.html">js的单线程和异步</a>
                </p>
                <p>参考一：
                    <a href="http://blog.csdn.net/u014787301/article/details/51984998">深入理解javascript异步编程障眼法&&h5 web worker实现多线程</a>
                </p>
                <p>参考一：
                    <a href="https://www.cnblogs.com/sprying/archive/2013/05/26/3100639.html">谈谈JavaScript的异步实现- 小方- 博客园</a>
                </p>
            </section>
            <section>
                <h4>鸣谢，陈树威师兄PPT</h4>
                <p>感谢大家观看</p>
                <p>
                    <small>王梦男</small>
                </p>
            </section>

        </div>
    </div>

    <script src="../lib/reveal/js/head.min.js"></script>
    <script src="../lib/reveal/reveal.js"></script>

    <script>
        // 以下为常见配置属性的默认值
        // {
        // 	controls: true, // 是否在右下角展示控制条
        // 	progress: true, // 是否显示演示的进度条
        // 	slideNumber: false, // 是否显示当前幻灯片的页数编号，也可以使用代码slideNumber: 'c / t' ，表示当前页/总页数。
        // 	history: false, // 是否将每个幻灯片改变加入到浏览器的历史记录中去
        // 	keyboard: true, // 是否启用键盘快捷键来导航
        // 	overview: true, // 是否启用幻灯片的概览模式，可使用"Esc"或"o"键来切换概览模式
        // 	center: true, // 是否将幻灯片垂直居中
        // 	touch: true, // 是否在触屏设备上启用触摸滑动切换
        // 	loop: false, // 是否循环演示
        // 	rtl: false, // 是否将演示的方向变成RTL，即从右往左
        // 	fragments: true, // 全局开启和关闭碎片。
        // 	autoSlide: 0, // 两个幻灯片之间自动切换的时间间隔（毫秒），当设置成 0 的时候则禁止自动切换，该值可以被幻灯片上的 ` data-autoslide` 属性覆盖
        // 	transition: 'default', // 切换过渡效果，有none/fade/slide/convex/concave/zoom
        // 	transitionSpeed: 'default', // 过渡速度，default/fast/slow
        // 	mouseWheel: true, //是否启用通过鼠标滚轮来切换幻灯片
        // }

        // 初始化幻灯片
        Reveal.initialize({
            //        history: true,
            transition: 'default',
            transitionSpeed: 'slow',
            dependencies: [{
                    src: '../plugin/markdown/marked.js'
                },
                {
                    src: '../plugin/markdown/markdown.js'
                },
                {
                    src: '../plugin/notes/notes.js',
                    async: true
                },
                {
                    src: '../plugin/highlight/highlight.js',
                    async: true,
                    callback: function () {
                        hljs.initHighlightingOnLoad();
                    }
                }
            ]
        });
    </script>
</body>

</html>